package com.demo.app.filter;

import com.demo.app.service.MyUserDetailsService;
import com.demo.app.util.JwtTokenUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.BeanIds;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author wangzhuangzhuang
 * @DESC:  接口访问鉴权过滤器
 * 当用户第一次登陆之后，我们将JWT令牌返回给了客户端，客户端应该将该令牌保存起来。在进行接口请求的时候，将令牌带上，
 * 放到HTTP的header里面，header的名字要和jwt.header的配置一致，这样服务端才能解析到。下面我们定义一个拦截器：
 *
 * 拦截接口请求，从请求request获取token，从token中解析得到用户名
 * 然后通过UserDetailsService获得系统用户（从数据库、或其他其存储介质）
 * 根据用户信息和JWT令牌，验证系统用户与用户输入的一致性，并判断JWT是否过期。如果没有过期，至此表明了该用户的确是该系统的用户。
 * 但是，你是系统用户不代表你可以访问所有的接口。所以需要构造UsernamePasswordAuthenticationToken传递用户、权限信息，并将这些信息通过authentication告知Spring Security。Spring Security会以此判断你的接口访问权限。
 * @date 2022-02-15 15:17
 */
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

	@Resource
	MyUserDetailsService myUserDetailsService;

	@Resource
	JwtTokenUtil jwtTokenUtil;


	@Override
	protected void doFilterInternal(HttpServletRequest request,
	                                HttpServletResponse response,
	                                FilterChain filterChain)
			throws ServletException, IOException {
		String jwtToken = request.getHeader(jwtTokenUtil.getHeader());
		if(jwtToken != null && !StringUtils.isEmpty(jwtToken)){
			String username = jwtTokenUtil.getUsernameFromToken(jwtToken);

			//如果可以正确的从JWT中提取用户信息，并且该用户未被授权
			if(username != null &&
					SecurityContextHolder.getContext().getAuthentication() == null){

				UserDetails userDetails = myUserDetailsService.loadUserByUsername(username);

				if(jwtTokenUtil.validateToken(jwtToken,userDetails)){
					//给使用该JWT令牌的用户进行授权
					UsernamePasswordAuthenticationToken authenticationToken
							= new UsernamePasswordAuthenticationToken(userDetails,null,
							userDetails.getAuthorities());

					SecurityContextHolder.getContext().setAuthentication(authenticationToken);

				}
			}
		}

		filterChain.doFilter(request,response);

	}


}